﻿package net.libra.loader
{
	import com.adobe.serialization.json.JSON;
	
	import flash.events.AsyncErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.NetConnection;
	import flash.net.Responder;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import net.libra.utils.ObjectUtil;

	/**
	 * 远程连接对象。对象用于调用远程服务器的方法，返回数据。
	 * @author DanielLu
	 */
	public class AMFLoader extends EventDispatcher implements ILoader 
	{
		//-----------------------------------------------------------------------
		private var connection : NetConnection;
		private var gateway : String;
		private var methodName : String;
		private var args : Array;

		private var loading : Boolean;
		private var data : Object;

		/**
		 * 创建一个<code>AMFLoader</code>对象。
		 * @param gateway		远程服务器地址
		 * @param methodName	远程方法名称
		 * @param args			远程方法参数
		 */
		public function AMFLoader (gateway : String = null,methodName : String = null,...args)
		{
			this.gateway = gateway;
			this.methodName = methodName;
			this.args = args;
			this.loading = false;
		}

		//--------------------------------------------------------------
		/**
		 * 设置远程服务器地址。
		 * @param gateway		远程服务器地址。
		 * @see	#getGateway()
		 */
		public function setGateway (gateway : String) : void
		{
			this.gateway = gateway;
		}

		/**
		 * 返回远程服务器地址。
		 * @return		远程服务器地址。
		 * @see	#setGateway()
		 */
		public function getGateway () : String
		{
			return this.gateway;
		}

		/**
		 * 设置远程方法名称。
		 * @param methodName	远程方法名称。
		 * @see	#getMethodName()
		 */
		public function setMethodName (methodName : String) : void
		{
			this.methodName = methodName;
		}

		/**
		 * 返回远程方法名称。
		 * @return		远程方法名称。
		 * @see	#setMethodName()
		 */
		public function getMethodName () : String
		{
			return this.methodName;
		}

		/**
		 * 设置远程方法参数。
		 * @param args		远程方法参数。
		 * @see	#getArgs()
		 */
		public function setArgs (...args) : void
		{
			this.args = args;
		}

		/**
		 * 返回远程方法参数。
		 * @return		远程方法参数。
		 * @see	#setArgs()
		 */
		public function getArgs () : Array
		{
			return this.args;
		}

		/**
		 * 是否正在加载
		 * @return		当前对象是否正在加载资源
		 */
		public function isLoading () : Boolean
		{
			return this.loading;
		}

		//--------------------------------------------------------------
		/**
		 * @inheritDoc
		 */
		public function addCompleteListener (listener : Function,priority : int = 0,useWeakReference : Boolean = false) : void
		{
			this.addEventListener( LoadEvent.ON_COMPLETE , listener , false , priority , useWeakReference );
		}

		/**
		 * @inheritDoc
		 */
		public function removeCompleteListener (listener : Function) : void
		{
			this.removeEventListener( LoadEvent.ON_COMPLETE , listener );
		}

		/**
		 * 发送加载完成的事件
		 */
		protected function fireComplete () : void
		{
			this.dispatchEvent( new LoadEvent( LoadEvent.ON_COMPLETE , this.data ) );
		}

		/**
		 * @inheritDoc
		 */
		public function addFailureListener (listener : Function,priority : int = 0,useWeakReference : Boolean = false) : void
		{
			this.addEventListener( LoadEvent.ON_FAILURE , listener , false , priority , useWeakReference );
		}

		/**
		 * @inheritDoc
		 */
		public function removeFailureListener (listener : Function) : void
		{
			this.removeEventListener( LoadEvent.ON_FAILURE , listener );
		}

		/**
		 * 发送加载失败的事件。
		 */
		protected function fireFailure () : void
		{
			this.dispatchEvent( new LoadEvent( LoadEvent.ON_FAILURE , this.data ) );
		}

		/**
		 * 空实现。
		 * @inheritDoc
		 */
		public function addProgressListener (listener : Function,priority : int = 0,useWeakReference : Boolean = false) : void
		{
			//do nothing
		}

		/**
		 * 空实现。
		 * @inheritDoc
		 */
		public function removeProgressListener (listener : Function) : void
		{
			//do nothing
		}

		//--------------------------------------------------------------
		/**
		 * 调用远程服务器上的方法，获取数据。
		 */
		public function doLoad () : void
		{
			if(! this.loading)
			{
				this.loading = true;
				//
				if(this.connection == null)this.connection = new NetConnection( );
				if(! this.connection.connected)
				{
					this.connection.connect( this.gateway );
				}
				
				this.connection.addEventListener( AsyncErrorEvent.ASYNC_ERROR , this.__onNetError );
				this.connection.addEventListener( IOErrorEvent.IO_ERROR , this.__onNetError );
				this.connection.addEventListener( NetStatusEvent.NET_STATUS , this.__onNetError );
				this.connection.addEventListener( SecurityErrorEvent.SECURITY_ERROR , this.__onNetError );
				//this.methodName = "cw.loginService.DoLogin"
				//this.args = [0, "nana1", "0:0:0"]
				var parameters : Array = [ this.methodName ,new Responder( this.__onResult , this.__onFault ) ].concat( this.args );
				this.connection.call.apply( this , parameters );
			}
		}
		
		public function doLoad2():void
		{
			if(! this.loading)
			{
				this.loading = true;
				//
				if(this.connection == null)this.connection = new NetConnection( );
				if(! this.connection.connected)
				{
					this.connection.connect( this.gateway + "?debug=1");
				}
				
				this.connection.addEventListener( AsyncErrorEvent.ASYNC_ERROR , this.__onNetError );
				this.connection.addEventListener( IOErrorEvent.IO_ERROR , this.__onNetError );
				this.connection.addEventListener( NetStatusEvent.NET_STATUS , this.__onNetError );
				this.connection.addEventListener( SecurityErrorEvent.SECURITY_ERROR , this.__onNetError );
				
				var parameters : Array = [ this.methodName ,new Responder( this.__onResult , this.__onFault ) ].concat( this.args );
				this.connection.call.apply( this , parameters );
			}
		}
		
		/**
		 * JSON形式请求数据，测试用
		 */
		public function doLoad3():void
		{
		    var urlLoader:URLLoader = new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE, okHandler);
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
			urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
			const BEFORE:String = "http://192.168.1.21/cw/game/GameServices/flashservices/json.php?";
			
//			var args=this.args;
//			for(var i=0;i<args.length;i++)
//			{
//				//args[i]=escape(args[i]);
//				args[i]=encodeURIComponent(args[i]);
//			}
			//var method:String = encodeURI(this.methodName);
			
			
			var params:String = this.methodName + "/" + args.join('/');// [0] + "/" + this.args[1] + "/" + this.args[2];
			params = BEFORE + params
			//params = gb2312ToUtf8(params);
			params = encodeUtf8(params);
			urlLoader.load(new URLRequest(params));
			
			
			
			function okHandler(event:Event):void
			{
				var obj:Object = JSON.decode(urlLoader.data);
				__onResult(obj);
			}
			function errorHandler(event:Event):void
			{
				__onFault(urlLoader.data);
			}
		}
		
		public function gb2312ToUtf8(str:String, charSet:String = "UTF-8"):String  
		{  
			var bytes:ByteArray = new ByteArray();  
			bytes.writeMultiByte(str, charSet);  
			return bytes.toString();  
		}
		
		/**utf-8编码,最为常用的一种*/
		public function encodeUtf8(str: String):String{
			if(str != null && str != "undefined"){
				var oriByteArr:ByteArray = new ByteArray();
				oriByteArr.writeUTFBytes(str);
				var tempByteArr:ByteArray = new ByteArray();
				for(var i:Number = 0; i < oriByteArr.length; i++){
					if(oriByteArr[i] == 194){
						tempByteArr.writeByte(oriByteArr[i + 1]);
						i++;
					}else if(oriByteArr[i] == 195){
						tempByteArr.writeByte(oriByteArr[i + 1] + 64);
						i++;
					}else{
						tempByteArr.writeByte(oriByteArr[i]);
					}
				}
				tempByteArr.position = 0;
				return tempByteArr.readMultiByte(tempByteArr.bytesAvailable, "chinese");
			}else{
				return "";
			}
		}
		
		public function doLoadLog(logFile:String):void
		{
			if(! this.loading)
			{
				this.loading = true;
				//
				if(this.connection == null)this.connection = new NetConnection( );
				if(! this.connection.connected)
				{
					this.connection.connect( this.gateway + "?log="+logFile);
				}
				
				this.connection.addEventListener( AsyncErrorEvent.ASYNC_ERROR , this.__onNetError );
				this.connection.addEventListener( IOErrorEvent.IO_ERROR , this.__onNetError );
				this.connection.addEventListener( NetStatusEvent.NET_STATUS , this.__onNetError );
				this.connection.addEventListener( SecurityErrorEvent.SECURITY_ERROR , this.__onNetError );
				
				var parameters : Array = [ this.methodName ,new Responder( this.__onResult , this.__onFault ) ].concat( this.args );
				this.connection.call.apply( this , parameters );
			}
		}

		private function disConnection () : void
		{
			if(this.connection)
			{
				this.connection.removeEventListener( AsyncErrorEvent.ASYNC_ERROR , this.__onNetError );
				this.connection.removeEventListener( IOErrorEvent.IO_ERROR , this.__onNetError );
				this.connection.removeEventListener( NetStatusEvent.NET_STATUS , this.__onNetError );
				this.connection.removeEventListener( SecurityErrorEvent.SECURITY_ERROR , this.__onNetError );
				this.connection.close( );
			}
			this.loading = false;
		}

		/**
		 * 返回获取的数据
		 * @return		从服务器返回的数据。
		 */
		public function getData () : Object
		{
			return this.data;
		}

		//-------------------------------------------------------------------------
		/**
		 * 当网络出现状况时
		 */
		private function __onNetError (evt : Event) : void
		{
			switch(evt.type)
			{
				case NetStatusEvent.NET_STATUS:
					var info:Object = (evt as NetStatusEvent).info;
					break;
			}
			this.disConnection( );
			this.data = evt;
			this.fireFailure( );
		}

		/**
		 * 当加载成功时
		 */
		private function __onResult (result : Object) : void
		{
			this.disConnection( );
			this.data = result;
			this.fireComplete( );
		}

		/**
		 * 当加载失败时
		 */
		private function __onFault (fault : Object) : void
		{
			this.disConnection( );
			this.data = fault;
			this.fireFailure( );
			printErrorLog(this.data);
		}
		public function printErrorLog(data:Object):void
		{
			if(data is String){
				Log.error(String(data));
			}else{
				var log:String = ObjectUtil.deepObjectToString(data);
				Log.error(log);
			}
		}
	}
}
